﻿#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.GamerServices;
using System.IO;

#endregion

namespace Tenebrous_Manor
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        #region SceneManager variables
        SceneManager.SceneManager sceneManager = new SceneManager.SceneManager();
            Texture2D titleScreen;
            Texture2D gameOver;
        #endregion

        SceneManager.MainEntranceScene main_ent_scene = new SceneManager.MainEntranceScene();
        SceneManager.EndingCutScene end_scene = new SceneManager.EndingCutScene();

        #region Navigation & Progress variable
            Navigation.RoomNavigator roomNav = new Navigation.RoomNavigator();
            Navigation.Triggers triggers = new Navigation.Triggers();
            String current_dialogue = " ";

            KeyboardState oldState;
            KeyboardState newState;

            Dialogue.Dialogue_keys[,] dialogue_array = new Dialogue.Dialogue_keys[GameConstants.ROW_COUNT, GameConstants.COL_COUNT];
        #endregion

        #region textures
        Texture2D tile;
        Texture2D blank;
        Texture2D enemyTexture;
        Texture2D enemyTexture2;
        Texture2D character;
        Texture2D characterEnd;
        Texture2D controlsScreen;
        Texture2D flashlight_right_left;
        Texture2D flashlight_up_down;
        #endregion

        #region Audio
        AudioEngine engine;
        SoundBank soundBank;
        WaveBank waveBank;

        AudioEmitter emitter = new AudioEmitter();
        AudioEmitter emitterShade = new AudioEmitter();
        AudioListener listener = new AudioListener();
        Cue BackgroundMusic;
        Cue GameOver;
        Cue Cutscene;
        Cue Notes;
        Cue cue;

        bool shadeSound = false;
        #endregion

        Map map;
        Player player;
        Menu menu;
        Credits credits;

        #region dialogue box
        TextBox textBox;
        TextBox noteBox;
        Vector2 noteBoxPosition = new Vector2(212.5f, 212.5f);
        #endregion

        SpriteFont font;

        //String file_name = "..\\..\\..\\Content\\Maps\\Foyer1.txt";

        int[,] array = new int[10, 10];

        int screenWidth, screenHeight;

        int tileSize = 85;

        Enemy enemy; //temporary

        bool dontDraw = false;

        bool GodMode = false;

        bool readingNotes = false;

        #region shade info
        Random rand = new Random();
        int triggerCounter = 1;
        bool firstSpawn = true; // true for testing, should be false when shade event trigger is done
        bool shadeSeen = false;
        bool safe;
        float shadeSpeed = 0.5f;
        int shadeForm = 1;
        float shadeMoveTimer = 0f;
        float shadeMoveTimerLimit = 1500f;
        float spawnTimerLimit;
        float spawnTimer = 0f;
        float distance;
        float angle;
        float energy = 1.0f;
        bool shadeSpawnedRoomChange = false;
        bool shadeTransitionSpawn = true;
        int sx = -5;
        int sy = -5;
        #endregion

        #region transition info
        bool transitioning = false;
        #endregion

        #region cutscene info
        bool endCutsceneStart = false;
        bool part2 = false;
        int sceneNumber = 0;
        bool sceneEnd = false;
        bool theEnd = false;
        #endregion

        public Game1()
            : base()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            engine = new AudioEngine(@"Content\Audio\Sounds.xgs");
            soundBank = new SoundBank(engine, @"Content\Audio\Sound Bank.xsb");
            waveBank = new WaveBank(engine, @"Content\Audio\Wave Bank.xwb");

            screenHeight = graphics.PreferredBackBufferHeight = 850;
            screenWidth = graphics.PreferredBackBufferWidth = 850;

            spawnTimerLimit = rand.Next(25000) + 5000;

            /*cue = soundBank.GetCue("Creepy Background");
            cue.Apply3D(listener, emitter);
            //cue.SetVariable("Volume", 0.35f);
            cue.Play();*/

            BackgroundMusic = soundBank.GetCue("Creepy Background");
            BackgroundMusic.Apply3D(listener, emitter);
            BackgroundMusic.SetVariable("Volume", 0.35f);

            Cutscene = soundBank.GetCue("Dark Walk");
            Cutscene.Apply3D(listener, emitter);
            //cue.SetVariable("Volume", 0.35f);

            Notes = soundBank.GetCue("Dark Walk");
            Notes.Apply3D(listener, emitter);
            //cue.SetVariable("Volume", 0.35f);

            GameOver = soundBank.GetCue("shadeconference");
            GameOver.Apply3D(listener, emitter);
            //cue.SetVariable("Volume", 0.35f);

            cue = soundBank.GetCue("Footsteps Sound Effect");
            cue.Apply3D(listener, emitterShade);

            this.Reset();
            base.Initialize();
        }

        protected void Reset()
        {
            roomNav.Initialize();
            Navigation.RoomGraphics.Initialize();
            Dialogue.Initialize();
            RandomizedClueLocations.Initialize();
            Randomization.RandomResearchNotes.Initialize();

            energy = 100.0f;
            GameBools.setAllFalse();
            player = new Player(characterEnd, character, flashlight_right_left, flashlight_up_down, new Vector2(85, 85));
            this.LoadFirstRoom();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);

            font = Content.Load<SpriteFont>("Font");
            titleScreen = Content.Load<Texture2D>("TitlePage");
            controlsScreen = Content.Load<Texture2D>("controls");
            tile = Content.Load<Texture2D>("tile");
            blank = Content.Load<Texture2D>("blank");
            gameOver = Content.Load<Texture2D>("gameover0");

            character = Content.Load<Texture2D>("Graphics\\characters\\spritesheet");
            characterEnd = Content.Load<Texture2D>("Graphics\\characters\\endcutscene_spritesheet");
            enemyTexture = Content.Load<Texture2D>("Graphics\\characters\\shadesheet2");
            enemyTexture2 = Content.Load<Texture2D>("Graphics\\characters\\shadegarysheet");

            flashlight_right_left = Content.Load<Texture2D>("flashlight_right2");
            flashlight_up_down = Content.Load<Texture2D>("flashlight_up2");

            this.LoadGraphicsTexture();

            enemy = new Enemy(enemyTexture, 0, 0);

            player = new Player(characterEnd, character, flashlight_right_left, flashlight_up_down, new Vector2(85, 85));
            this.LoadFirstRoom();

            menu = new Menu(tile, font);

            credits = new Credits(blank, font, screenWidth, screenHeight);

            textBox = new TextBox(blank, font, new Vector2(400,200));
            noteBox = new TextBox(blank, font, new Vector2(425, 425));
        }

        protected void LoadGraphicsTexture()
        {
            #region basement
            Navigation.RoomGraphics.bighole[0] = Content.Load<Texture2D>("Graphics\\basement\\bighole1");
            Navigation.RoomGraphics.bighole[1] = Content.Load<Texture2D>("Graphics\\basement\\bighole2");
            Navigation.RoomGraphics.bighole[2] = Content.Load<Texture2D>("Graphics\\basement\\bighole3");
            #endregion

            #region bedroom
            Navigation.RoomGraphics.bed[0, 0] = Content.Load<Texture2D>("Graphics\\bedroom\\bedtopleft");
            Navigation.RoomGraphics.bed[0, 1] = Content.Load<Texture2D>("Graphics\\bedroom\\bedtopmid");
            Navigation.RoomGraphics.bed[0, 2] = Content.Load<Texture2D>("Graphics\\bedroom\\bedtopright");
            Navigation.RoomGraphics.bed[1, 0] = Content.Load<Texture2D>("Graphics\\bedroom\\bedmidleft");
            Navigation.RoomGraphics.bed[1, 1] = Content.Load<Texture2D>("Graphics\\bedroom\\bedmid");
            Navigation.RoomGraphics.bed[1, 2] = Content.Load<Texture2D>("Graphics\\bedroom\\bedmidright");
            Navigation.RoomGraphics.bed[2, 0] = Content.Load<Texture2D>("Graphics\\bedroom\\bedbottomleft");
            Navigation.RoomGraphics.bed[2, 1] = Content.Load<Texture2D>("Graphics\\bedroom\\bedbottommid");
            Navigation.RoomGraphics.bed[2, 2] = Content.Load<Texture2D>("Graphics\\bedroom\\bedbottomright");

            Navigation.RoomGraphics.cupboard[0] = Content.Load<Texture2D>("Graphics\\bedroom\\cupboardleft2");
            Navigation.RoomGraphics.cupboard[1] = Content.Load<Texture2D>("Graphics\\bedroom\\cupboardright2");

            Navigation.RoomGraphics.mirror[0] = Content.Load<Texture2D>("Graphics\\upper landing\\mirror1");
            Navigation.RoomGraphics.mirror[1] = Content.Load<Texture2D>("Graphics\\upper landing\\mirror2");
            Navigation.RoomGraphics.mirror[2] = Content.Load<Texture2D>("Graphics\\upper landing\\mirror3");
            #endregion

            #region floors
            Navigation.RoomGraphics.kitchenfloor[0] = Content.Load<Texture2D>("Graphics\\floors\\kitchenfloor1");
            Navigation.RoomGraphics.kitchenfloor[1] = Content.Load<Texture2D>("Graphics\\floors\\kitchenfloor2");
            Navigation.RoomGraphics.labfloor = Content.Load<Texture2D>("Graphics\\floors\\labfloor");
            Navigation.RoomGraphics.stonefloor = Content.Load<Texture2D>("Graphics\\floors\\stonefloor");
            Navigation.RoomGraphics.woodfloor[0] = Content.Load<Texture2D>("Graphics\\floors\\woodfloor1");
            Navigation.RoomGraphics.woodfloor[1] = Content.Load<Texture2D>("Graphics\\floors\\woodfloor2");
            Navigation.RoomGraphics.woodfloor[3] = Content.Load<Texture2D>("Graphics\\floors\\woodfloor3");
            Navigation.RoomGraphics.woodfloor[2] = Content.Load<Texture2D>("Graphics\\floors\\woodfloor4");
            Navigation.RoomGraphics.woodfloor[4] = Content.Load<Texture2D>("Graphics\\floors\\woodfloor5");
            #endregion

            #region foyer
            Navigation.RoomGraphics.upper_stair[0, 0] = Content.Load<Texture2D>("Graphics\\foyer\\stairsleft");
            Navigation.RoomGraphics.upper_stair[0, 1] = Content.Load<Texture2D>("Graphics\\foyer\\stairsmid");
            Navigation.RoomGraphics.upper_stair[0, 2] = Content.Load<Texture2D>("Graphics\\foyer\\stairsright");
            Navigation.RoomGraphics.upper_stair[1, 0] = Content.Load<Texture2D>("Graphics\\foyer\\stairsbottomleft");
            Navigation.RoomGraphics.upper_stair[1, 1] = Content.Load<Texture2D>("Graphics\\foyer\\stairsmid");
            Navigation.RoomGraphics.upper_stair[1, 2] = Content.Load<Texture2D>("Graphics\\foyer\\stairsbottomright");
            #endregion

            #region junkroom
            Navigation.RoomGraphics.junk = Content.Load<Texture2D>("Graphics\\junk room\\junk");
            #endregion

            #region lab
            Navigation.RoomGraphics.lab_equipment[0, 0] = Content.Load<Texture2D>("Graphics\\lab\\machinetopleft");
            Navigation.RoomGraphics.lab_equipment[0, 1] = Content.Load<Texture2D>("Graphics\\lab\\machinetopright");
            Navigation.RoomGraphics.lab_equipment[1, 0] = Content.Load<Texture2D>("Graphics\\lab\\machinebottomleft");
            Navigation.RoomGraphics.lab_equipment[1, 1] = Content.Load<Texture2D>("Graphics\\lab\\machinebottomright");
            #endregion

            #region lower landing
            Navigation.RoomGraphics.lower_stair[0] = Content.Load<Texture2D>("Graphics\\lower landing\\stairslowerlandingtop");
            Navigation.RoomGraphics.lower_stair[1] = Content.Load<Texture2D>("Graphics\\lower landing\\stairslowerlandingmid");
            Navigation.RoomGraphics.lower_stair[2] = Content.Load<Texture2D>("Graphics\\lower landing\\stairslowerlandingbottom");
            Navigation.RoomGraphics.box = Content.Load<Texture2D>("Graphics\\lower landing\\box");
            #endregion

            #region kitchen
            Navigation.RoomGraphics.counter = Content.Load<Texture2D>("Graphics\\kitchen\\counter");
            Navigation.RoomGraphics.countercorner = Content.Load<Texture2D>("Graphics\\kitchen\\countercorner");
            Navigation.RoomGraphics.fridge = Content.Load<Texture2D>("Graphics\\kitchen\\fridgeright");
            Navigation.RoomGraphics.sink = Content.Load<Texture2D>("Graphics\\kitchen\\sink");
            Navigation.RoomGraphics.stove = Content.Load<Texture2D>("Graphics\\kitchen\\stove");
            Navigation.RoomGraphics.table[0, 0] = Content.Load<Texture2D>("Graphics\\kitchen\\tabletopleft2");
            Navigation.RoomGraphics.table[0, 1] = Content.Load<Texture2D>("Graphics\\kitchen\\tabletopright2");
            Navigation.RoomGraphics.table[1, 0] = Content.Load<Texture2D>("Graphics\\kitchen\\tablebottomleft2");
            Navigation.RoomGraphics.table[1, 1] = Content.Load<Texture2D>("Graphics\\kitchen\\tablebottomright2");
            #endregion

            #region main entrance
            Navigation.RoomGraphics.carpet[0, 0] = Content.Load<Texture2D>("Graphics\\main entrance\\topleftcarpet");
            Navigation.RoomGraphics.carpet[0, 1] = Content.Load<Texture2D>("Graphics\\main entrance\\topmidcarpet");
            Navigation.RoomGraphics.carpet[0, 2] = Content.Load<Texture2D>("Graphics\\main entrance\\toprightcarpet");
            Navigation.RoomGraphics.carpet[1, 0] = Content.Load<Texture2D>("Graphics\\main entrance\\midleftcarpet");
            Navigation.RoomGraphics.carpet[1, 1] = Content.Load<Texture2D>("Graphics\\main entrance\\midcarpet");
            Navigation.RoomGraphics.carpet[1, 2] = Content.Load<Texture2D>("Graphics\\main entrance\\midrightcarpet");
            Navigation.RoomGraphics.carpet[2, 0] = Content.Load<Texture2D>("Graphics\\main entrance\\bottomleftcarpet");
            Navigation.RoomGraphics.carpet[2, 1] = Content.Load<Texture2D>("Graphics\\main entrance\\bottommidcarpet");
            Navigation.RoomGraphics.carpet[2, 2] = Content.Load<Texture2D>("Graphics\\main entrance\\bottomrightcarpet");
            Navigation.RoomGraphics.desktop = Content.Load<Texture2D>("Graphics\\main entrance\\desk2top");
            Navigation.RoomGraphics.deskbottom = Content.Load<Texture2D>("Graphics\\main entrance\\desk2bottombook");
            #endregion

            #region misc
            Navigation.RoomGraphics.door = Content.Load<Texture2D>("Graphics\\misc\\door");
            Navigation.RoomGraphics.doorcarpetup = Content.Load<Texture2D>("Graphics\\misc\\doorcarpet");
            Navigation.RoomGraphics.doorcarpetbottom = Content.Load<Texture2D>("Graphics\\misc\\doorcarpetbottom");
            Navigation.RoomGraphics.doorcarpetleft = Content.Load<Texture2D>("Graphics\\misc\\doorcarpetleft");
            Navigation.RoomGraphics.doorcarpetright = Content.Load<Texture2D>("Graphics\\misc\\doorcarpetright");
            Navigation.RoomGraphics.hole[0] = Content.Load<Texture2D>("Graphics\\misc\\hole1");
            Navigation.RoomGraphics.hole[1] = Content.Load<Texture2D>("Graphics\\misc\\hole2");
            Navigation.RoomGraphics.hole[2] = Content.Load<Texture2D>("Graphics\\misc\\hole3");
            Navigation.RoomGraphics.key = Content.Load<Texture2D>("Graphics\\misc\\key");
            Navigation.RoomGraphics.leftdoor = Content.Load<Texture2D>("Graphics\\misc\\leftdoor");
            Navigation.RoomGraphics.leftdoubledoorcarpet = Content.Load<Texture2D>("Graphics\\misc\\leftdoubledoorcarpet");
            Navigation.RoomGraphics.note[0] = Content.Load<Texture2D>("Graphics\\misc\\note1");
            Navigation.RoomGraphics.note[1] = Content.Load<Texture2D>("Graphics\\misc\\note2");
            Navigation.RoomGraphics.note[2] = Content.Load<Texture2D>("Graphics\\misc\\note3");
            Navigation.RoomGraphics.rightdoor = Content.Load<Texture2D>("Graphics\\misc\\rightdoor");
            Navigation.RoomGraphics.rightdoubledoorcarpet = Content.Load<Texture2D>("Graphics\\misc\\rightdoubledoorcarpet");
            Navigation.RoomGraphics.screwdriver = Content.Load<Texture2D>("Graphics\\misc\\screwdriver");
            #endregion

            #region study
            Navigation.RoomGraphics.bookshelf = Content.Load<Texture2D>("Graphics\\study\\bookshelf");
            Navigation.RoomGraphics.bookshelfback = Content.Load<Texture2D>("Graphics\\study\\bookshelfback");
            Navigation.RoomGraphics.studydesk[0, 0] = Content.Load<Texture2D>("Graphics\\study\\desk3topleft");
            Navigation.RoomGraphics.studydesk[0, 1] = Content.Load<Texture2D>("Graphics\\study\\desk3topright");
            Navigation.RoomGraphics.studydesk[1, 0] = Content.Load<Texture2D>("Graphics\\study\\desk3midleft");
            Navigation.RoomGraphics.studydesk[1, 1] = Content.Load<Texture2D>("Graphics\\study\\desk3midright");
            Navigation.RoomGraphics.studydesk[2, 0] = Content.Load<Texture2D>("Graphics\\study\\desk3bottomleft");
            Navigation.RoomGraphics.studydesk[2, 1] = Content.Load<Texture2D>("Graphics\\study\\desk3bottomright");
            Navigation.RoomGraphics.trapdoor = Content.Load<Texture2D>("Graphics\\study\\trapdoor");
            #endregion

            #region upper landing
            Navigation.RoomGraphics.stairtop[0, 0] = Content.Load<Texture2D>("Graphics\\upper landing\\stairstopleft1");
            Navigation.RoomGraphics.stairtop[0, 1] = Content.Load<Texture2D>("Graphics\\upper landing\\stairstopmid1");
            Navigation.RoomGraphics.stairtop[0, 2] = Content.Load<Texture2D>("Graphics\\upper landing\\stairstopright1");
            Navigation.RoomGraphics.stairtop[1, 0] = Content.Load<Texture2D>("Graphics\\upper landing\\stairstopleft2");
            Navigation.RoomGraphics.stairtop[1, 1] = Content.Load<Texture2D>("Graphics\\upper landing\\stairstopmid2");
            Navigation.RoomGraphics.stairtop[1, 2] = Content.Load<Texture2D>("Graphics\\upper landing\\stairstopright2");
            Navigation.RoomGraphics.brokendoor = Content.Load<Texture2D>("Graphics\\upper landing\\brokendoor");
            #endregion

            #region wall
            Navigation.RoomGraphics.sidesandbottomwall = Content.Load<Texture2D>("Graphics\\walls\\sidesandbottomwall");
            Navigation.RoomGraphics.stonewall = Content.Load<Texture2D>("Graphics\\walls\\stonewall");
            Navigation.RoomGraphics.wallpaper[0] = Content.Load<Texture2D>("Graphics\\walls\\wallpaper1");
            Navigation.RoomGraphics.wallpaper[1] = Content.Load<Texture2D>("Graphics\\walls\\wallpaper2");
            Navigation.RoomGraphics.wallpaper[2] = Content.Load<Texture2D>("Graphics\\walls\\wallpaper3");
            Navigation.RoomGraphics.wallpaper[3] = Content.Load<Texture2D>("Graphics\\walls\\wallpaper4");
            Navigation.RoomGraphics.woodwall = Content.Load<Texture2D>("Graphics\\walls\\woodwall");
            #endregion

            #region random furniture
            /*Randomization.FurnitureGraphics.chair[0] = Content.Load<Texture2D>("Graphics\\random furniture\\chair");
            Randomization.FurnitureGraphics.chair[1] = Content.Load<Texture2D>("Graphics\\random furniture\\chair2");
            Randomization.FurnitureGraphics.chair[2] = Content.Load<Texture2D>("Graphics\\random furniture\\chairback");
            Randomization.FurnitureGraphics.chair[3] = Content.Load<Texture2D>("Graphics\\random furniture\\chairfront");*/

            Randomization.FurnitureGraphics.hole[0] = Content.Load<Texture2D>("Graphics\\random furniture\\bighole");
            Randomization.FurnitureGraphics.hole[1] = Content.Load<Texture2D>("Graphics\\random furniture\\bighole4");
            #endregion
        }
        protected void LoadRoom()
        {
            roomNav.Load(ref array);
            //Randomization.RandomizedFurniture.setRandomFurniture(ref array, roomNav.getCurrentRoom());
            map = new Map(array, tile, new Vector2(85, 85), font);
            Navigation.DialogueMap.LoadCurrentMap(roomNav.getCurrentRoom(), ref dialogue_array);
            //player.setPosition(roomNav.next_x_index, roomNav.next_y_index);
        }
        protected void LoadFirstRoom()
        {
            roomNav.Load(ref array);
            //Randomization.RandomizedFurniture.setRandomFurniture(ref array, roomNav.getCurrentRoom());
            map = new Map(array, tile, new Vector2(85, 85), font);
            player.setPosition(roomNav.next_x_index, roomNav.next_y_index);
        }

        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();

            sceneManager.Update();

            // TODO: Add your update logic here
            switch (sceneManager.usingScene)
            {
                #region TITLE
                case SceneManager.SceneManager.sceneType.TITLE :

                    this.Reset();
                    this.LoadFirstRoom();

                    BackgroundMusic.Stop(AudioStopOptions.Immediate);
                    GameOver.Stop(AudioStopOptions.Immediate);
                    Notes.Stop(AudioStopOptions.Immediate);
                    Cutscene.Stop(AudioStopOptions.Immediate);

                    menu.Update(gameTime);

                    if (Keyboard.GetState().IsKeyDown(Keys.Enter))
                    {
                        //this.LoadContent();
                        ///map.Update(gameTime);
                        switch(menu.getMenuSelection())
                        {
                            case 0 :
                                sceneManager.changeTo(SceneManager.SceneManager.sceneType.ENTRANCE_CUTSCENE);
                                main_ent_scene.Reset();
                                break;
                            case 1 :
                                sceneManager.changeTo(SceneManager.SceneManager.sceneType.CONTROLS);
                                break;
                            case 2 :
                                credits.reset();
                                sceneManager.changeTo(SceneManager.SceneManager.sceneType.CREDITS);
                                break;
                            case 3 :
                                Exit();
                                break;
                        }
                    }
                    break;
                #endregion
                #region ENTRANCE CUTSCENE
                case SceneManager.SceneManager.sceneType.ENTRANCE_CUTSCENE:
                    if(!Cutscene.IsPlaying)
                        Cutscene.Play();

                    if (main_ent_scene.Update(gameTime, ref player, ref textBox))
                    {
                        if (Cutscene.IsPlaying) Cutscene.Stop(AudioStopOptions.Immediate);
                        sceneManager.changeTo(SceneManager.SceneManager.sceneType.GAME);
                    }
                    break;
                #endregion
                #region GAME
                case SceneManager.SceneManager.sceneType.GAME :

                    if (GameBools.getGameBool(GameBools.GameBool.END))
                    {
                        end_scene.Initialize(enemyTexture);
                        sceneManager.changeTo(SceneManager.SceneManager.sceneType.END_CUTSCENE);
                    }

                    if (Cutscene.IsPlaying && !readingNotes)
                    {
                        Cutscene.Stop(AudioStopOptions.Immediate);
                    }

                    if (!BackgroundMusic.IsPlaying && !Cutscene.IsPlaying && !Notes.IsPlaying)
                    {
                        BackgroundMusic.Play();
                    }

                    Dialogue.Update();
                    
                    if (roomNav.hasSwitched())
                    {
                        transitioning = true;
                    }

                    if (transitioning)
                    {
                        this.LoadRoom();
                        beginTransition(gameTime);
                        if (this.roomNav.getCurrentRoom() == Navigation.Room.MAIN_ENTRANCE)
                        {
                            safe = true;
                            //enemy.setRoom(Navigation.Room.MAIN_ENTRANCE);
                        }
                        else
                        {
                            safe = false;
                            //if (enemy.isSpawned()) shadeSpawnedRoomChange = true;
                        }
                        enemy.shadeDespawn();
                        //shadeMoveTimer = 0.0f;
                    }
                    else
                    {
                        player.spriteMove(gameTime);
                        player.Update(gameTime, ref array, ref roomNav);
                    }

                    #region keyboard cheats
                    //Complete Game
                    if (Keyboard.GetState().IsKeyDown(Keys.T))
                    {
                        GameBools.setAllTrue();
                    }

                    //Get all research Note
                    if(Keyboard.GetState().IsKeyDown(Keys.R))
                    {
                        for (int i = 0; i <= Randomization.RandomResearchNotes.research_notes.Length - 1; i++)
                        {
                            Randomization.RandomResearchNotes.research_notes[i].foundNote();
                        }
                    }

                    //Don't Draw
                    if(Keyboard.GetState().IsKeyDown(Keys.I))
                    {
                        dontDraw = !dontDraw;
                    }

                    //God Mode
                    if(Keyboard.GetState().IsKeyDown(Keys.G))
                    {
                        GodMode = true;
                    }

                    #endregion

                    #region TextBox
                    newState = Keyboard.GetState();

                    if (newState.IsKeyDown(Keys.Enter) && !oldState.IsKeyDown(Keys.Enter))
                    {
                        {

                            if (noteBox.triggered)
                            {
                                if (noteBox.done_printing)
                                {
                                    noteBox.triggered = !noteBox.triggered;
                                    readingNotes = false;
                                }
                                else
                                {
                                    noteBox.continued = true;
                                }
                            }
                            else
                            {
                                if (textBox.done_printing)
                                {
                                    textBox.triggered = !textBox.triggered;
                                }
                                else
                                    textBox.continued = true;   
                            }

                            if (textBox.triggered && textBox.done_printing)
                            {
                                current_dialogue = triggers.CheckTrigger(ref dialogue_array, roomNav.getCurrentRoom(), player.getFacing(),
                                                                    player.getXIndex(), player.getYIndex());
                                Dialogue.Update();

                                if (current_dialogue.Equals(Dialogue.dialogue[Dialogue.Dialogue_keys.DESK_WITH_BOOK]))
                                {
                                    textBox.triggered = false;
                                    textBox.done_printing = true;

                                    readingNotes = true;
                                    noteBox.triggered = true;
                                    noteBox.done_printing = false;
                                    noteBox.setString(Randomization.RandomResearchNotes.getFoundNotes());
                                }
                                else
                                {
                                    textBox.setString(current_dialogue);
                                }
                            }
                            
                        }
                        
                        // shade movement modifier and formed based on triggers
                        shadeSpeed = triggers.getSpeed();
                        shadeForm = triggers.getShadeForm();
                        enemy.newForm(shadeForm);
                    }

                    if (readingNotes)
                    {
                        if (BackgroundMusic.IsPlaying)
                        {
                            BackgroundMusic.Stop(AudioStopOptions.Immediate);
                            Notes.Play();
                        }
                    }
                    else
                    {
                        if (Notes.IsPlaying)
                        {
                            Notes.Stop(AudioStopOptions.Immediate);
                            BackgroundMusic.Play();
                        }
                    }

                    textBox.Update(gameTime, ref player.position);
                    noteBox.Update(gameTime, ref noteBoxPosition);
                    oldState = newState;

                    #endregion

                    if (!GodMode)
                    {
                        energy = player.alphaFlash(enemy, energy);
                        if (energy > 1.0f) energy = 1.0f;
                        else if (energy <= 0.0f)
                        {
                            energy = 0.0f;
                            sceneManager.changeTo(SceneManager.SceneManager.sceneType.GAMEOVER);
                        }
                    }

                    #region  Shade Updates
                    #region proximity
                    distance = (float)Math.Sqrt(Math.Pow(enemy.getShadeX() - player.getXIndex(), 2) + Math.Pow(enemy.getShadeY() - player.getYIndex(), 2));

                    if (player.getXIndex() == enemy.getShadeX() && player.getYIndex() == enemy.getShadeY()) energy = 0.0f;
                    else if (distance <= 3) // check max range
                    {
                        angle = (float)Math.Acos((enemy.getShadeX() - player.getXIndex()) / distance);
                        if (enemy.getShadeY() - player.getYIndex() > 0) angle = (float)(2 * Math.PI - angle);

                        // check between correct angles
                        if (player.getFacing() == Facing.UP && angle >= Math.PI / 3 && angle <= 2 * Math.PI / 3)
                        {
                            shadeSeen = true;
                            cue.Stop(AudioStopOptions.Immediate);
                        }
                        else if (player.getFacing() == Facing.LEFT && angle >= 5 * Math.PI / 6 && angle <= 7 * Math.PI / 6)
                        {
                            shadeSeen = true;
                            cue.Stop(AudioStopOptions.Immediate);
                        }
                        else if (player.getFacing() == Facing.DOWN && angle >= 4 * Math.PI / 3 && angle <= 5 * Math.PI / 3)
                        {
                            shadeSeen = true;
                            cue.Stop(AudioStopOptions.Immediate);
                        }
                        else if (player.getFacing() == Facing.RIGHT && ((angle >= 0 && angle <= Math.PI / 6)) || (angle >= 11 * Math.PI / 6 && angle <= 2 * Math.PI))
                        {
                            shadeSeen = true;
                            cue.Stop(AudioStopOptions.Immediate);
                        }
                        else
                        {
                            if (distance > 0)
                            {
                                emitterShade.Position = new Vector3(enemy.getShadeX(), enemy.getShadeY(), 0);
                                cue.SetVariable("Volume", 0.5f / distance);
                                if (!cue.IsPlaying) cue.Play();
                                shadeSound = true;
                            }
                            else cue.Stop(AudioStopOptions.Immediate);
                            shadeSeen = false;
                        }
                    }
                    else
                    {
                        shadeSeen = false;
                        shadeSound = false;
                        cue.Stop(AudioStopOptions.Immediate);
                    }
                    #endregion //proximity
                    #region shade movement
                    if (!shadeSeen)
                    {
                        if (enemy.isSpawned()) shadeMoveTimer += ((float)gameTime.ElapsedGameTime.TotalMilliseconds) * shadeSpeed;
                        else if (firstSpawn && !safe) spawnTimer += (float)gameTime.ElapsedGameTime.TotalMilliseconds * (shadeSpeed / 0.5f);
                    }
                    if (shadeMoveTimer >= shadeMoveTimerLimit)
                    {
                        // to implement later: room change while being chased
                        shadeMoveTimer = 0;
                        enemy.move(player.getXIndex(), player.getYIndex());
                    }
                    if (spawnTimer >= spawnTimerLimit)
                    {
                        Random rand = new Random();
                        enemy.spawnShade(false, player.getXIndex(), player.getYIndex());
                        enemy.setRoom(roomNav.getCurrentRoom());
                        spawnTimer = 0;
                        spawnTimerLimit = rand.Next(25000) + 5000;
                    }

                    /*
                    if (enemy.isSpawned()) // despawns if shade is faced directly
                    {
                        int diff = 0;
                        if (player.getFacing() == Facing.UP)
                        {
                            diff = player.getYIndex() - enemy.getShadeY();
                            if (player.getXIndex() == enemy.getShadeX() && (diff > 0 && diff < 2)) enemy.shadeDespawn();
                        }
                        else if (player.getFacing() == Facing.DOWN)
                        {
                            diff = enemy.getShadeY() - player.getYIndex();
                            if (player.getXIndex() == enemy.getShadeX() && (diff > 0 && diff < 2)) enemy.shadeDespawn();
                        }
                        else if (player.getFacing() == Facing.RIGHT)
                        {
                            diff = enemy.getShadeX() - player.getXIndex();
                            if (player.getYIndex() == enemy.getShadeY() && (diff > 0 && diff < 2)) enemy.shadeDespawn();
                        }
                        else if (player.getFacing() == Facing.LEFT)
                        {
                            diff = player.getXIndex() - enemy.getShadeX();
                            if (player.getYIndex() == enemy.getShadeY() && (diff > 0 && diff < 2)) enemy.shadeDespawn();
                        }
                        else
                        {
                            // facing Error
                        }
                    }
                    */
                    #endregion // shade movement
                    #region room transitions
                    /*if (enemy.getRoom() == roomNav.getOldRoom() && !safe) // FIX THIS
                    {
                        if (shadeSpawnedRoomChange)
                        {
                            sx = player.getXIndex();
                            sy = player.getYIndex();
                            shadeSpawnedRoomChange = false;
                            shadeTransitionSpawn = false;
                        }
                        shadeMoveTimer += (float)gameTime.ElapsedGameTime.TotalMilliseconds;
                        if (shadeMoveTimer >= shadeMoveTimerLimit)
                        {
                            shadeMoveTimer = 0.0f;
                            enemy.spawnShade(true, sx, sy); // find x and y of doors
                            enemy.setRoom(roomNav.getCurrentRoom());
                            shadeTransitionSpawn = true;
                        }
                    }
                    else if (enemy.getRoom() == roomNav.getCurrentRoom() && roomNav.getOldRoom() != Navigation.Room.MAIN_ENTRANCE && !shadeTransitionSpawn)
                    { // FIX THIS AS WELL. main entrance is despawn room for shade...
                        energy = 0f;
                    }*/
                    #endregion // room transition
                    #endregion // shade updates

                    break;
                #endregion
                #region MIRROR CUTSCENE
                case SceneManager.SceneManager.sceneType.MIRROR_CUTSCENE:
                    //SceneManager.Cutscenes.playEntrance(gameTime, player, textBox);       // Cutscenes didn't exist. re-enable when fixed.
                    //sceneManager.changeTo(SceneManager.SceneManager.sceneType.GAME);
                    /* When Gary walks up the stairs to the upper landing, start mirror cutscene. Gary's flashlight turns off and after a second, all
                     * the lights turn on, and there is a mirror infront of him. He sees himself in the mirror, and then the mirror version of himself
                     * becomes black for ~1 frame, then it goes back to normal. After a split second, the lights go out again and his flashlight turns
                     * back on, but the mirror is now missing.
                     * */
                    //firstSpawn = true;
                    // turn of firstSpawn in overhead when this section is done.
                    break;
                #endregion
                #region END CUTSCENE
                case SceneManager.SceneManager.sceneType.END_CUTSCENE:
                    if(end_scene.Update(gameTime, ref player, ref textBox))
                    {
                        sceneManager.changeTo(SceneManager.SceneManager.sceneType.CREDITS);
                    }
                    break;
                #endregion
                #region CONTROLS
                case SceneManager.SceneManager.sceneType.CONTROLS :
                    if (Keyboard.GetState().IsKeyDown(Keys.Enter))
                    {
                        sceneManager.changeTo(SceneManager.SceneManager.sceneType.TITLE);
                    }
                    break;
                #endregion
                #region CREDITS
                case SceneManager.SceneManager.sceneType.CREDITS :
                    credits.Update(gameTime);
                    if(!Cutscene.IsPlaying)
                        Cutscene.Play();
                    if (Keyboard.GetState().IsKeyDown(Keys.Enter))
                    {
                        if (Cutscene.IsPlaying) Cutscene.Stop(AudioStopOptions.Immediate);
                        sceneManager.changeTo(SceneManager.SceneManager.sceneType.TITLE);
                    }
                    break;
                #endregion
                #region GAMEOVER
                case SceneManager.SceneManager.sceneType.GAMEOVER :
                    if (!GameOver.IsPlaying)
                    {
                        if (BackgroundMusic.IsPlaying) BackgroundMusic.Stop(AudioStopOptions.Immediate);
                        if (cue.IsPlaying) cue.Stop(AudioStopOptions.Immediate);
                        GameOver.Play();
                    }
                    if (Keyboard.GetState().IsKeyDown(Keys.Enter))
                    {
                        sceneManager.changeTo(SceneManager.SceneManager.sceneType.TITLE);
                    }
                    break;
                #endregion


            }
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin();

            switch (sceneManager.usingScene)
            {
                #region TITLE
                case SceneManager.SceneManager.sceneType.TITLE :
                    spriteBatch.Draw(titleScreen, new Rectangle(0, 0, 850, 850), Color.White);
                    menu.Draw(spriteBatch);
                    //spriteBatch.Draw(startButton, new Rectangle(450, 450, 300, 100), Color.White); 
                    break;
                #endregion
                #region ENTRANCE CUTSCENE
                case SceneManager.SceneManager.sceneType.ENTRANCE_CUTSCENE :
                    //SceneManager.Cutscenes.Draw(spriteBatch);
                    main_ent_scene.Draw(spriteBatch, font, blank, ref player, ref textBox);
                    break;
                #endregion
                #region GAME
                case SceneManager.SceneManager.sceneType.GAME :
                    map.Draw(spriteBatch);
                    Navigation.RoomGraphics.Draw(spriteBatch, roomNav.getCurrentRoom());
                    if (!dontDraw)
                    {
                        if (enemy.isSpawned()) enemy.Draw(spriteBatch);

                        if (transitioning)
                            spriteBatch.Draw(tile, new Rectangle(0, 0, 850, 850), Color.Black);

                        player.Draw(spriteBatch);
                    }
                    //roomNav.Draw(spriteBatch, font);
                    //spriteBatch.DrawString(font, "Energy: " + energy * 100, new Vector2(650.0f, 125.0f), Color.White);
                    //roomNav.Draw(spriteBatch, font);
                    //spriteBatch.DrawString(font, current_dialogue, new Vector2(100, 400), Color.Red);

                    //FOR TESTING PURPOSES. LOCATION OF RANDOMIZED CLUE
                    /*spriteBatch.DrawString(font, RandomizedClueLocations.screwdriver.ToString(), new Vector2(10, 80), Color.Blue);
                    spriteBatch.DrawString(font, RandomizedClueLocations.studyKey.ToString(), new Vector2(10, 120), Color.Blue);
                    spriteBatch.DrawString(font, RandomizedClueLocations.studyNote.ToString(), new Vector2(10, 160), Color.Blue);
                    spriteBatch.DrawString(font, RandomizedClueLocations.lever.ToString(), new Vector2(10, 200), Color.Blue);*/
                    /*spriteBatch.DrawString(font, "" + shadeSpeed, new Vector2(10, 80), Color.Blue);
                    spriteBatch.DrawString(font, "" + shadeForm, new Vector2(10, 120), Color.Blue);*/

                    noteBox.Draw(spriteBatch);
                    textBox.Draw(spriteBatch);
                    
                    
                    //spriteBatch.DrawString(font, "index: " + array[4], new Vector2(20, 40), Color.Blue);
                    break;
                #endregion
                #region END CUTSCENE
                case SceneManager.SceneManager.sceneType.END_CUTSCENE:
                    end_scene.Draw(spriteBatch, font, ref player, ref textBox);
                    break;
                #endregion
                #region CONTROLS
                case SceneManager.SceneManager.sceneType.CONTROLS :
                    spriteBatch.Draw(controlsScreen, new Rectangle(123, 223, 604, 404), Color.White);
                    break;
                #endregion
                #region CREDITS
                case SceneManager.SceneManager.sceneType.CREDITS :
                    credits.Draw(spriteBatch);
                    break;
                #endregion
                #region GAMEOVER
                case SceneManager.SceneManager.sceneType.GAMEOVER :
                    spriteBatch.Draw(gameOver, new Rectangle(0, 0, 850, 850), Color.White);
                    break;
                #endregion
            }

            if (sceneManager.changingScene)
            {
                spriteBatch.Draw(tile, new Rectangle(0, 0, screenWidth, screenHeight), new Color(0, 0, 0, sceneManager.alpha));
            }

            spriteBatch.End();

            base.Draw(gameTime);
        }

        public void beginTransition(GameTime gameTime)
        {
            switch (player.getFacing())
            {
                case Facing.UP:
                    if (player.getLocation().Y + player.getVelocity() * 4 >= roomNav.next_y_index * tileSize)
                        player.setPosition(roomNav.next_x_index, roomNav.next_y_index);

                    if (!(player.getLocation().X == roomNav.next_x_index * tileSize &&
                        player.getLocation().Y == roomNav.next_y_index * tileSize))
                    {
                        player.incrementLocation(new Vector2(0, player.getVelocity() * 4));
                    }
                    else
                    {
                        player.setXIndex(roomNav.next_x_index);
                        player.setYIndex(roomNav.next_y_index);
                        transitioning = false;
                    }
                    break;
                case Facing.DOWN:
                    if (player.getLocation().Y - player.getVelocity() * 4 <= roomNav.next_y_index * tileSize)
                        player.setPosition(roomNav.next_x_index, roomNav.next_y_index);

                    if (!(player.getLocation().X == roomNav.next_x_index * tileSize && 
                        player.getLocation().Y == roomNav.next_y_index * tileSize))
                    {
                        player.incrementLocation(new Vector2(0, -player.getVelocity() * 4));
                    }
                    else
                    {
                        player.setXIndex(roomNav.next_x_index);
                        player.setYIndex(roomNav.next_y_index);
                        transitioning = false;
                    }
                    break;
                case Facing.RIGHT:
                    if (player.getLocation().X + player.getVelocity() * 4 <= roomNav.next_x_index * tileSize)
                        player.setPosition(roomNav.next_x_index, roomNav.next_y_index);

                    if (!(player.getLocation().X == roomNav.next_x_index * 85 && player.getLocation().Y == roomNav.next_y_index * 85))
                    {
                       player.incrementLocation(new Vector2(-player.getVelocity() * 4, 0));
                    }
                    else
                    {
                        player.setXIndex(roomNav.next_x_index);
                        player.setYIndex(roomNav.next_y_index);
                        transitioning = false;
                    }
                    break;
                case Facing.LEFT:
                    if (player.getLocation().X - player.getVelocity() * 4 >= roomNav.next_x_index * tileSize)
                        player.setPosition(roomNav.next_x_index, roomNav.next_y_index);

                    if (!(player.getLocation().X == roomNav.next_x_index * 85 && player.getLocation().Y == roomNav.next_y_index * 85))
                    {
                        player.incrementLocation(new Vector2(player.getVelocity() * 4, 0));  
                    }
                    else
                    {
                        player.setXIndex(roomNav.next_x_index);
                        player.setYIndex(roomNav.next_y_index);
                        transitioning = false;
                    }
                    break;
            }
        }
    }
}

